package org.walkerljl.commons.designer;

import java.util.concurrent.ExecutorService;

public class Designer<Event> {

    private final ExecutorService executorService;

    private final TaskStructure<Event> taskStructure;

    private TaskExecuteEngineBuilder<Event> taskExecuteEngineBuilder;

    private volatile boolean ready = false;

    public Designer(ExecutorService executorService) {
        this.executorService = executorService;
        this.taskStructure = new TaskStructure<Event>();
    }

    public EventHandlerGroup<Event> begin(EventHandler<Event>... eventHandlers) {
        return taskStructure.start(eventHandlers);
    }

    public EventHandlerGroup<Event> after(EventHandler<Event>... eventHandlers) {
        return taskStructure.after(eventHandlers);
    }

    public synchronized void end() {
        if (!ready) {
            taskStructure.ready();
            taskExecuteEngineBuilder = new TaskExecuteEngineBuilder<Event>(taskStructure, executorService);
            ready = true;
        }
    }

    public Event publish(Event event, long timeout) {
        assertState();
        return taskExecuteEngineBuilder.build(event, timeout).run();
    }

    public Event publish(Event event) {
        return publish(event, (long) 0);
    }

    public void publish(Event event, Callback<Event> callback) {
        assertState();
        if (callback == null) {
            throw new IllegalArgumentException("callback can not be null");
        }
        taskExecuteEngineBuilder.build(event, 0, callback).run();
    }

    public boolean isReady() {
        return ready;
    }

    private void assertState() {
        if (!ready) {
            throw new IllegalStateException("designer not started.");
        }
    }

}
